// Key Driver
// (c) jimon game studio

#include "CKeyDriver.h"

#ifdef JE_WIN
#include <windows.h>
#endif

namespace je
{
	namespace input
	{
		//! Constructor
		CKeyDriver::CKeyDriver(device::IWindow * window)
			:Window(window),KeyStream(256)
		{
			for(s32 i = 0; i < 256;i++)
			{
				KeyDown[i] = false;
				KeyHits[i] = 0;
				KeyHitsFlush[i] = 0;
			}
		}

		//! Destructor
		CKeyDriver::~CKeyDriver()
		{
		}

		//! Return true if hit
		u1 CKeyDriver::IsHit(KeyCode Key)
		{
			s32 Hit = KeyHits[Key];
			if(Hit)
				KeyHitsFlush[Key]++;
			return Hit ? true : false;
		}

		//! Return true if down
		u1 CKeyDriver::IsDown(KeyCode Key,u1 TrueWhenDownMessageArrive)
		{
			if(TrueWhenDownMessageArrive)
				return KeyDownMessages[Key];
			else
				return KeyDown[Key];
		}

		//! Flush Keys Hits
		void CKeyDriver::FlushKeysHits()
		{
			for(s32 i = 0; i < 256;i++)
			{
				KeyHits[i] -= KeyHitsFlush[i];
				if(KeyHits[i] < 0)
					KeyHits[i] = 0;
				KeyDownMessages[i] = false;
				KeyHitsFlush[i] = 0;
			}
		}

		//! Get Keys Stream, last element of stream is KC_NULL
		KeyCode * CKeyDriver::GetKeysStream()
		{
			KeyCode * Codes = NULL;
			JENEW_A(Codes,KeyCode,KeyStream.GetSize()+1)
			if(KeyStream.GetSize()>0)
				memcpy(Codes,KeyStream.GetPtr(),sizeof(KeyCode)*KeyStream.GetSize());
			Codes[KeyStream.GetSize()] = KC_NULL;
			return Codes;
		}

		//! Get Text Stream
		jeStringd CKeyDriver::GetTextStream()
		{
			#ifdef JE_WIN

			jeStringd Text;

			for(u32 i=0;i<KeyStream.GetSize();i++)
			{
				u8 VirtCode = KeyStream[i];
				UINT ScanCode = MapVirtualKey(VirtCode,0);
				if(!VirtCode)
					continue;
				u8 KeyState[256];
				GetKeyboardState(KeyState);
				#ifdef JE_UNICODE
				je_wchar_t Out = 0;
				ToUnicode(VirtCode,ScanCode,KeyState,&Out,1,0);
				#else
				u16 Out = 0;
				ToAscii(VirtCode,ScanCode,KeyState,&Out,0);
				#endif
				jeschar TextOut[2] = {(jeschar)Out,0};
				Text = Text + TextOut;
			}

			return Text;

			#endif

			#ifdef JE_LINUX
			return "TODO";
			#endif
		}

		//! Flush Keys Stream
		void CKeyDriver::FlushKeysStream()
		{
			KeyStream.Clear();
		}

		//! Set Down
		void CKeyDriver::SetDown(KeyCode Key,u1 Down)
		{
			if(Down && (!KeyDown[Key]))
				KeyHits[Key]++;

			if(Down)
				KeyDownMessages[Key] = Down;

			if(Down)
				KeyStream.InsertElement(Key);

			KeyDown[Key] = Down;
		}


	}
}
